package io.bdmc.core.eu;

import io.bdmc.common.exception.CMSException;
import io.bdmc.common.utils.ByteUtil;
import io.bdmc.core.msp2000.DataBuild;
import io.bdmc.core.msp2000.DataParse;
import io.bdmc.core.msp2000.Msp2000AlarmProcess;
import io.bdmc.core.msp2000.model.Msp2000Ter2Platform;
import io.bdmc.core.udp.UdpClientSendData;
import io.bdmc.modules.bss.entity.*;
import io.bdmc.modules.bss.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;

import java.util.List;

@Slf4j
@Component
@EnableAsync
public class EUDataRead {
    @Autowired
    UdpClientSendData _udpClient;

    @Autowired
    IDeviceMachineFecService _fecService;

    @Autowired
    IDeviceMachineFecModuleService _fecModuleService;

    @Autowired
    Msp2000AlarmProcess _msp2000AlarmProcess;

    @Autowired
    IDeviceMachineEdfaService _edfaService;

    @Autowired
    IDeviceMachineRtService _rtService;

    @Autowired
    IDeviceMachineFspService _fspService;

    @Async
    void sendFec1U(DeviceDevice dev) {
        try {
            String data = senUDP401Data(dev.getIpaddr(), dev.getDevicePort());
            DeviceMachineFec fecData = DataParse.parseDeviceFec(data);
            updateEUDeviceSN(dev, fecData.getDeviceSn());
            updateEUDiskSN(dev, fecData.getDiskSn());
            fecData.setDeviceId(dev.getDeviceId());
            _fecService.save(fecData);
            if (fecData.getFecModuleList() != null) {
                fecData.getFecModuleList().forEach(item -> item.setMachineFecId(fecData.getMachineFecId()));
            }
            _fecModuleService.saveBatch(fecData.getFecModuleList());
            _msp2000AlarmProcess.fecAlarm(fecData, dev);
        } catch (Exception ex) {
            log.error(ex.getMessage());
        }

    }

    @Async
    void sendEDFA1U(DeviceDevice dev) {
        try {
            String data = senUDP401Data(dev.getIpaddr(), dev.getDevicePort());
            DeviceMachineEdfa edfa = DataParse.parseDevice1UBA(data);
            updateEUDeviceSN(dev, edfa.getDeviceSn());
            updateEUDiskSN(dev, edfa.getDiskSn());
            
            edfa.setDeviceId(dev.getDeviceId());
            edfa.setDiskSn(edfa.getDeviceSn());
            _edfaService.save(edfa);
            _msp2000AlarmProcess.edfaAlarm(edfa, dev);
        } catch (Exception ex) {
            log.error(ex.getMessage());
        }
    }

    @Async
    void sendRT1U(DeviceDevice dev) {
        try {
            String data = senUDP401Data(dev.getIpaddr(), dev.getDevicePort());
            DeviceMachineRt rt = DataParse.parseDevice1URt(data);
            updateEUDeviceSN(dev, rt.getDeviceSn());
            updateEUDiskSN(dev, rt.getDiskSn());
            rt.setDeviceId(dev.getDeviceId());
            _rtService.save(rt);
            _msp2000AlarmProcess.rtAlarm(rt, dev);
        } catch (Exception ex) {
            log.error(ex.getMessage());
        }
    }

    @Async
    void sendFSPFU(DeviceDevice dev) {
        try {
            List<DeviceMachineFsp> fspList = sendFuFspData(dev.getIpaddr(), dev.getDevicePort());
            if (fspList == null || fspList.size() == 0) {
                log.error("4u-fsp 数据为空。");
                return;
            }
            String deviceSN = fspList.get(0).getDeviceSN();
            if (StringUtils.isNotEmpty(deviceSN)
                    && (StringUtils.isEmpty(dev.getDeviceSn()) || !dev.getDeviceSn().equals(deviceSN))) {
                dev.setDeviceSn(deviceSN);
                dev.updateById();
            }
            for (DeviceMachineFsp fsp : fspList) {
                fsp.setDeviceId(dev.getDeviceId());
                _fspService.save(fsp);
                _msp2000AlarmProcess.fspAlarm(fsp, dev);
            }
        } catch (Exception ex) {
            log.error(ex.getMessage());
        }
    }

    /**
     * 发送1U设备读取
     * 
     * @param ip   ip地址
     * @param port 端口
     * @return 返回值
     */
    private String senUDP401Data(String ip, int port) {
        try {
            String sendMsg = DataBuild.build0401Msg();
            String receiveMsg = _udpClient.sendPollCommand(ip, port, sendMsg);
            Msp2000Ter2Platform msg = DataParse.parseAllMsg(ByteUtil.hexToBytes(receiveMsg.toUpperCase()));
            if (msg.getComm().equals("0401")) {
                return msg.getData().substring(8);
            } else {
                throw new CMSException("senUDP401Data：数据解析异常。" + msg.getData());
            }
        } catch (Exception ex) {
            throw new CMSException(
                    "senUDP401Data：数据解析异常，" + "senUDP401Data：" + ip + "," + port + "," + ex.getMessage());
        }
    }

    // 发送4u设备 fsp
    private List<DeviceMachineFsp> sendFuFspData(String ip, int port) {
        String readThresholdCmd = DataBuild.buildRadFspOlpCmd("1F");
        String readCurrentDataCmd = DataBuild.buildRadFspOlpCmd("10");
        String receiveThresholdData = _udpClient.sendDataByUdpOLP(ip, port, readThresholdCmd);
        String receiveCurrentData = _udpClient.sendDataByUdpOLP(ip, port, readCurrentDataCmd);
        if (receiveThresholdData.length() > 0 && receiveCurrentData.length() > 0) {
            return DataParse.parseDeviceMachineFspOLPS(receiveThresholdData.substring(10),
                    receiveCurrentData.substring(10));
        }
        return null;
    }

    private void updateEUDeviceSN(DeviceDevice device, String deviceSN) {
        if (StringUtils.isNotEmpty(deviceSN) && (StringUtils.isEmpty(device.getDeviceSn()) ||
                !device.getDeviceSn().equals(deviceSN))) {
            device.setDeviceSn(deviceSN);
            device.updateById();
        }
    }

    private void updateEUDiskSN(DeviceDevice device, String diskSN) {
        if (StringUtils.isNotEmpty(diskSN) && (StringUtils.isEmpty(device.getRemark()) ||
                !device.getRemark().equals(diskSN))) {
            device.setRemark(diskSN);
            device.updateById();
        }
    }
}
